from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *

from ui.Ui_planed_task_editor_dialog import Ui_Dialog_task_editor
from database.db import Database


class Planed_task_editor_signal(QObject):
    editor_task = Signal(int)


class Planed_task_editor_dialog(QDialog):
        
    def __init__(self, parent=None):
        super(Planed_task_editor_dialog, self).__init__(parent)
        self.ui = Ui_Dialog_task_editor()
        self.ui.setupUi(self)
        self.setWindowTitle("编辑任务")
        
        self.setModal(True)  # 设置窗体为模态窗口，必须为True
        self.setWindowFlags(Qt.WindowCloseButtonHint)  # 设置窗体仅显示关闭按钮
        
        self.task_id = -1
        self.devices = []
        self.scripts = {}
        self.signal = Planed_task_editor_signal()
 

        self.init_ui()
        self.init_signal_slot()


    def init_ui(self):
        self.listWidgetItem = QListWidgetItem()
        self.script_comboBox = QComboBox()
        self.ui.listWidget_script.addItem(self.listWidgetItem)
        self.ui.listWidget_script.setItemWidget(self.listWidgetItem,self.script_comboBox)
    
        self.ui.comboBox_loop_day.clear()
        self.ui.comboBox_loop_hour.clear()
        for i in range(31):
            self.ui.comboBox_loop_day.addItem(f'{i}天')
        
        for i in range(24):
            self.ui.comboBox_loop_hour.addItem(f'{i}时')

        self.ui.lineEdit_ip.setReadOnly(True)
        self.ui.lineEdit_port.setReadOnly(True)
        self.ui.lineEdit_user.setReadOnly(True)
        self.ui.lineEdit_password.setReadOnly(True)
        self.ui.lineEdit_supplier.setReadOnly(True)
        self.ui.lineEdit_model.setReadOnly(True)
        self.ui.lineEdit_position.setReadOnly(True)
        self.ui.textEdit_script_content.setReadOnly(True)
        self.ui.textEdit_script_info.setReadOnly(True)
        self.ui.textEdit_textfsm.setReadOnly(True)
        self.ui.lineEdit_exec_times.setValidator(QIntValidator(0,65535)) # 限制只能输入数字 范围

    def init_signal_slot(self):
        self.ui.pushButton_ok.clicked.connect(self.slot_btn_ok)
        self.ui.listWidget_script.itemClicked.connect(self.slot_click_item)
        self.script_comboBox.currentIndexChanged.connect(self.slot_comboBox_script_index_changed)
        self.ui.comboBox_device.currentIndexChanged.connect(self.slot_comboBox_device_index_changed)


    def clear_data(self):
        self.ui.lineEdit_ip.clear()
        self.ui.lineEdit_port.clear()
        self.ui.lineEdit_user.clear()
        self.ui.lineEdit_password.clear()
        self.ui.lineEdit_supplier.clear()
        self.ui.lineEdit_model.clear()
        self.ui.lineEdit_position.clear()
        self.ui.textEdit_script_content.clear()
        self.ui.textEdit_textfsm.clear()
        self.ui.textEdit_script_info.clear()
        self.ui.comboBox_device.clear()
        self.script_comboBox.clear()
        
    
    def load_private_scripts(self,device_id:int):
        db = Database()
        # 私有脚本
        if device_id >= 0:
            self.scripts['私有脚本'] = []
            script_id_list = db.select('private_script_device',['script_id'],f'device_id={device_id}')
            for script_id in script_id_list:
                script_data = db.select('scripts',['name','content','textfsm','info'],f'id={script_id[0]}')
                data = {
                    'id':script_id[0],
                    'name' : script_data[0][0],
                    'content' : script_data[0][1],
                    'textfsm' : script_data[0][2],
                    'info':script_data[0][3],
                }
                self.scripts['私有脚本'].append(data)
        db.close_conn()



    def load_public_scripts(self):
        db = Database()
        # 公有脚本
        group_list = db.select('script_group',['name'])
        for group in group_list:
            group_name = group[0]
            self.scripts[group_name] = []
            # 查询脚本数据
            script_list = db.select('scripts',['id','name','content','textfsm','info'],f'group_name="{group_name}"')
            for script_data in script_list:
                data = {
                    'id':script_data[0],
                    'name' : script_data[1],
                    'content' : script_data[2],
                    'textfsm' : script_data[3],
                    'info':script_data[4],
                }
                self.scripts[group_name].append(data)
        db.close_conn()

    def load_devices_data(self):
        '''
            加载所有设备数据 到 self.devices
        '''
        # 查询设备数据
        db = Database()
        fields = ['id','name','ip','port','user','password','supplier','model','position']
        device_list = db.select('devices',fields)
        del self.devices[:] # 清空列表
        for device in device_list:
            data = {
                'id':device[0],
                'name':device[1],
                'ip':device[2],
                'port':device[3],
                'user':device[4],
                'password':device[5],
                'supplier':device[6],
                'model':device[7],
                'position':device[8],
            }
            self.devices.append(data)
        db.close_conn()


    def get_device_data(self,device_id:int) -> dict:
        '''
            获取指定设备数据
        '''
        # 查询设备数据
        for device in self.devices:
            if device['id'] == device_id:
                return device


    def get_script_data(self,group_name,index:int) -> dict|None:
        '''
            获取脚本数据\n
            group_name:分组名称\n
            index:索引(listWidget的项目是从1创建的,索引传入时候应该-1)\n
            res:{'name':xx,'content':xx,'textfsm':xx,'info':xx}
        '''
        data_list = self.scripts.get(group_name)
        if not data_list:
            return 

        if len(data_list) <= index:
            return 
        
        return data_list[index]


    def is_group_name_exisit(self,group_name:str):
        for i in range(self.script_comboBox.count()):
            if self.script_comboBox.itemText(i) == group_name:
                return True
        return False    

    def is_group_name_valid(self,group_name:str) -> bool:
        for k in self.scripts:
            if k == group_name: return True
        return False

    def is_device_id_valid(self,device_id:int) -> bool:
        for i in range(len(self.devices)) :
                if device_id == self.devices[i]['id']:
                    return True
        return False
    
    def clear_script_item(self):
        # 清理listwidget
        max_row = self.ui.listWidget_script.count()
        for i in range(max_row-1,0,-1):
            self.ui.listWidget_script.takeItem(i)
    
    def set_script_item(self,group_name:str):
        '''
            设置新的分组 并刷新数据
        '''
        # 检测分组有效性
        if not self.is_group_name_valid(group_name): return

        self.clear_script_item()
       
        # 加载数据
        for data in self.scripts[group_name]:
            self.ui.listWidget_script.addItem(data['name'])

    
    def set_device_data(self,data:dict):
        self.ui.lineEdit_ip.setText(data['ip'])
        self.ui.lineEdit_port.setText(data['port'])
        self.ui.lineEdit_user.setText(data['user'])
        self.ui.lineEdit_password.setText(data['password'])
        self.ui.lineEdit_supplier.setText(data['supplier'])
        self.ui.lineEdit_model.setText(data['model'])
        self.ui.lineEdit_position.setText(data['position'])







    def slot_show(self,task_id:int):
        self.task_id = task_id
        #清理数据
        self.clear_data()

        # 加载所有设备数据
        self.load_devices_data()

        # 加载公有脚本数据
        self.load_public_scripts()
        # 加载公有脚本分组
        for name in self.scripts:
            self.script_comboBox.addItem(name)

        # 初始化comboBox device
        for device in self.devices:
            self.ui.comboBox_device.addItem(device['name'])

        # 指定设备 脚本
        db = Database()
        task_data = db.select('tasks',['name','device_id','script_id','start_time','exec_times','loop_day','loop_hour'],f'id={task_id}')[0]
        
        data = {
            'name':task_data[0],
            'device_id':task_data[1],
            'script_id':task_data[2],
            'start_time':task_data[3],
            'exec_times':task_data[4],
            'loop_day':task_data[5],
            'loop_hour':task_data[6],
        }
        
        for i in range(len(self.devices)):
            if data['device_id'] == self.devices[i]['id']:
                self.ui.comboBox_device.setCurrentIndex(i)
                break
        
        for name,data_list in self.scripts.items():
            for i in range(len(data_list)):
                if data_list[i]['id'] == data['script_id']:
                    # 指定分组
                    self.script_comboBox.setCurrentText(name)
                    # 点击脚本
                    item = self.ui.listWidget_script.item(i+1)
                    self.ui.listWidget_script.setCurrentRow(i+1)
                    self.ui.listWidget_script.itemClicked.emit(item)


        # 设置默认参数
        start_time = data['start_time']
        exec_times = str(data['exec_times'])
        loop_day = data['loop_day']
        loop_hour = data['loop_hour']
        self.ui.lineEdit_name.setText(data['name'])
        self.ui.dateTimeEdit_star_time.setDateTime(QDateTime.fromString(start_time,'yyyy-MM-dd HH:mm'))
        
        self.ui.lineEdit_exec_times.setText(exec_times)
        self.ui.comboBox_loop_day.setCurrentText(f'{loop_day}天')
        self.ui.comboBox_loop_hour.setCurrentText(f'{loop_hour}时')

        self.show()



    def slot_comboBox_script_index_changed(self):
        '''
            脚本分组选项切换 槽函数
        '''
        group_name = self.script_comboBox.currentText()
        self.set_script_item(group_name)

    

    def slot_comboBox_device_index_changed(self,index:int):
        if index < 0: return
        if index >= len(self.devices) : return
        device_id = self.devices[index]['id']
        # 加载私有脚本
        self.load_private_scripts(device_id)
        # 创建私有脚本分组
        if not self.is_group_name_exisit('私有脚本'):
            self.script_comboBox.addItem('私有脚本')

        # 重载脚本分组数据
        if self.script_comboBox.currentText() == '私有脚本':
            self.set_script_item('私有脚本')

        # 设置设备数据
        device_data = self.get_device_data(device_id)
        self.set_device_data(device_data)

    
    def slot_click_item(self,item:QListWidgetItem):
        '''
            脚本 listWidget 点击槽函数
        '''
        index = self.ui.listWidget_script.row(item)
        group_name = self.script_comboBox.currentText()
        data = self.get_script_data(group_name,index-1)
        if not data:
            return
        self.ui.textEdit_script_content.setText(data['content'])
        self.ui.textEdit_textfsm.setText(data['textfsm'])
        self.ui.textEdit_script_info.setText(data['info'])
    
    def slot_btn_ok(self):
        # 读取ui数据
        device_index = self.ui.comboBox_device.currentIndex()
        script_group_name = self.script_comboBox.currentText()
        script_index = self.ui.listWidget_script.currentRow()

        data = {
            'name':self.ui.lineEdit_name.text(),
            'device_id':self.devices[device_index]['id'],
            'script_id':self.get_script_data(script_group_name,script_index - 1)['id'],
            'start_time':self.ui.dateTimeEdit_star_time.dateTime().toString('yyyy-MM-dd HH:mm'),
            'exec_times':self.ui.lineEdit_exec_times.text(),
            'loop_day':self.ui.comboBox_loop_day.currentText().replace('天',''),
            'loop_hour':self.ui.comboBox_loop_hour.currentText().replace('时',''),
        }

        db = Database()
        fields = ['name','device_id','script_id','start_time','exec_times','loop_day','loop_hour']
        values = (data['name'],data['device_id'],data['script_id'],data['start_time'],data['exec_times'],data['loop_day'],data['loop_hour'],)
        db.update('tasks',fields,values,f'id={self.task_id}')
        db.close_conn()

        # 发送信号更新 task_widget
        self.signal.editor_task.emit(self.task_id )

        self.hide()


    def slot_checkBox_start_time(self,check_status:int):
        if check_status == Qt.Checked:
            self.ui.dateTimeEdit_star_time.setDisabled(False)
        else:
            self.ui.dateTimeEdit_star_time.setDisabled(True)